#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdint.h>

// Defines para configuração
#define _GNU_SOURCE
#define ATRIB 15
#define ERRORS_LIMIT 255
#define FALHA 0
#define FALSE -1
#define LIM_SIMBOLOS 255
#define LIM_TOKEN 3
#define MEMORIA 1024
#define NUM_INSTRUCOES 16
#define SPACE 14
#define STOP 11
#define SUCESSO 1
#define TRUE -2

//Estruturas Globais
struct erro {
    char mensagem[255];
    int linha;
} TabErros[ERRORS_LIMIT];

struct instrucao {
    char nome[7];
    short int codigo;
    short int operandos;
} TabInstrucoes[NUM_INSTRUCOES];

struct macro {
    char nome[255];
    int contExpancao;
    int contParametros;
    char corpo[512];
    char listaParametros[20];
} TabMacros[50];

struct simbolo {
    char simbolo[255];
    short int endereco;
} MatrizSimbolos[LIM_SIMBOLOS];

struct saida {
    char saida[255];
} VetSaida[MEMORIA];

// Variáveis globais
int programCounter, sybolCounter, fileLine, tokenCounter, errorCounter, numOperandos, locSTOP;
int countMacros = 0;
char nomeArquivo[255], caminhoArquivo[255];
short int MEM[MEMORIA], REALOC[MEMORIA];

//Funções auxiliares globais
void armazenaErro(char * mensagem, int linha);
int buscaInstrucao(char * token);
int buscaSimbolo(char * simbolo);
int contaOcorrencia(char * texto, char caractere);
int criaArquivoBin();
int criaArquivoBinEmul(char * caminhoAbsolutoBin, FILE * arquivoBin);
void emulador(int v);
void finalizaPrograma(int condicaoDeSaida);
void gravaEndereco(char * endereco);
void gravaInstrucao(int indiceInstrucao);
int gravaSimboloMatriz(char * simbolo);
void gravaSimboloSaida(char * simbolo);
void inicializaTabInstrucoes();
int isNumber(char * string);
FILE * openFile();
char * removeChar(char * texto, char caractere);
void segundaPassagem();
char * strToUpper(char * str);
char * trataLinha(char * linha);
void trataCaminhoArquivo(char * caminhoArq);
int trataDadosEntrada(char *palavra);